diff options
Diffstat (limited to 'src/pages/blog/[...date].astro')
-rw-r--r-- | src/pages/blog/[...date].astro | 251 |
1 files changed, 109 insertions, 142 deletions
diff --git a/src/pages/blog/[...date].astro b/src/pages/blog/[...date].astro index 1742baa..d66ac8e 100644 --- a/src/pages/blog/[...date].astro +++ b/src/pages/blog/[...date].astro @@ -1,161 +1,128 @@ --- import type { - GetStaticPaths, InferGetStaticParamsType, InferGetStaticPropsType, } from "astro"; -import { getCollection } from "astro:content"; import Base from "@layouts/Base.astro"; import DateSelector from "@components/DateSelector.astro"; -import BlogCard from "@components/BlogCard.astro"; -import { sortLastCreated } from "@lib/collection/helpers"; +import SimplePostList from "@components/templates/SimplePostList.astro"; +import { datePaths, sortLastCreated } from "@lib/collection/helpers"; -export const getStaticPaths = (async () => { - const posts = await getCollection("blog"); - - const archive = { - years: new Set<number>(), - monthsByYear: new Map<string, Set<number>>(), - daysByMonth: new Map<string, Set<number>>(), - postsByDate: new Map<string, typeof posts>(), - sortedDates: [] as string[], - }; - - const getYMD = (date: Date) => { - const y = date.getFullYear(); - const m = date.getMonth() + 1; - const d = date.getDate(); - return { y, m, d }; - }; - - for (const post of posts) { - const { y, m, d } = getYMD(post.data.dateCreated); - - archive.years.add(y); - - if (!archive.monthsByYear.has(y.toString())) { - archive.monthsByYear.set(y.toString(), new Set()); - } - archive.monthsByYear.get(y.toString())!.add(m); - - const ym = `${y}/${String(m).padStart(2, "0")}`; - if (!archive.daysByMonth.has(ym)) archive.daysByMonth.set(ym, new Set()); - archive.daysByMonth.get(ym)!.add(d); - - const ymd = `${ym}/${String(d).padStart(2, "0")}`; - if (!archive.postsByDate.has(ymd)) archive.postsByDate.set(ymd, []); - archive.postsByDate.get(ymd)!.push(post); - } - - archive.sortedDates = Array.from(archive.postsByDate.keys()).sort(); - - const paths = []; - - const sortedYears = Array.from(archive.years).sort(); - - const lastYear = Math.max(...sortedYears.map(Number)); - paths.push({ - params: { year: undefined }, - props: { - posts: posts.filter((p) => - p.data.dateCreated.getFullYear() === lastYear - ), - next: undefined, - previous: sortedYears?.[sortedYears.length - 2], - years: sortedYears, - months: Array.from(archive.monthsByYear.get(lastYear.toString()) ?? []), - }, - }); - - for (const y of sortedYears) { - const yearPosts = posts.filter((p) => - p.data.dateCreated.getFullYear() === Number(y) - ); - const idx = sortedYears.indexOf(y); - paths.push({ - params: { year: y }, - props: { - posts: yearPosts, - next: sortedYears?.[idx + 1], - previous: sortedYears?.[idx - 1], - years: sortedYears, - months: Array.from(archive.monthsByYear.get(y.toString()) ?? []), - }, - }); - } - - const allMonths = Array.from(archive.monthsByYear.entries()) - .flatMap(([year, mset]) => - Array.from(mset).map((m) => `${year}/${String(m).padStart(2, "0")}`) - ) - .sort(); - - for (const [y, months] of archive.monthsByYear) { - const sortedMonths = Array.from(months).sort(); - for (const m of sortedMonths) { - const monthPosts = posts.filter((p) => { - const d = p.data.dateCreated; - return ( - d.getFullYear() === Number(y) && - d.getMonth() + 1 === m - ); - }); - - const ym = `${y}/${String(m).padStart(2, "0")}`; - const idx = allMonths.indexOf(ym); - - paths.push({ - params: { year: ym }, - props: { - posts: monthPosts, - next: allMonths?.[idx + 1], - previous: allMonths?.[idx - 1], - years: sortedYears, - months: Array.from(months).sort(), - days: Array.from(archive.daysByMonth.get(ym) ?? []).sort(), - }, - }); - } - } - - for (let i = 0; i < archive.sortedDates.length; i++) { - const ymd = archive.sortedDates[i]; - const [y, m] = ymd.split("/"); - paths.push({ - params: { year: ymd }, - props: { - posts: archive.postsByDate.get(ymd) ?? [], - next: archive.sortedDates?.[i + 1], - previous: archive.sortedDates?.[i - 1], - years: sortedYears, - months: Array.from(archive.monthsByYear.get(y) ?? []).sort(), - days: Array.from(archive.daysByMonth.get(`${y}/${m}`) ?? []).sort(), - }, - }); - } - - return paths; -}) satisfies GetStaticPaths; +export const getStaticPaths = datePaths; export type Params = InferGetStaticParamsType<typeof getStaticPaths>; export type Props = InferGetStaticPropsType<typeof getStaticPaths>; -const title = "Blog"; -const description = "Latest articles."; - let { posts, previous, next, years, months, days } = Astro.props; posts = posts.sort(sortLastCreated); -const date = posts[0].data.dateCreated as Date; + +const dateParts = Astro.params.date?.split("/").map(Number); +const y = dateParts?.[0]; +const m = dateParts?.[1] ?? 1; +const d = dateParts?.[2] ?? 3; +const date = (y !== undefined) ? new Date(Date.UTC(y, m - 1, d)) : undefined; + +const format = date === undefined + ? undefined + : new Intl.DateTimeFormat("pt-PT", { + year: y === undefined ? undefined : "numeric", + month: dateParts?.[1] === undefined ? undefined : "long", + day: dateParts?.[2] === undefined ? undefined : "numeric", + }).format(date); +const title = "Publicações" + (format !== undefined ? ` -- ${format}` : ""); +const description = "Ultímas publicações" + + (format !== undefined ? ` do dia ${format}` : "") + "."; --- <Base {title} {description}> - <main> - <h2>Blogue</h2> - {date && <DateSelector {date} {years} {months} {days} />} - {posts.map((post) => <BlogCard {...post} />)} - <div> - {previous && <a href={`/blog/${Astro.props.previous}`}>Previous</a>} - {next && <a href={`/blog/${Astro.props.next}`}>Next</a>} - </div> + <main + itemprop="mainContentOfPage" + itemscope + itemtype="https://schema.org/WebPageElement" + > + <section + id="posts" + itemprop="citation" + itemscope + itemtype="http://schema.org/Blog" + > + <h2 itemprop="name description">{title}</h2> + <DateSelector {date} {years} {months} {days} /> + { + (next || previous) && ( + <nav> + { + previous && ( + <p> + < <a href={`/blog/${Astro.props.previous}`}>Anterior</a> + </p> + ) + } + <span class="small">{format}</span> + { + next && ( + <p><a href={`/blog/${Astro.props.next}`}>Próximo</a> ></p> + ) + } + </nav> + ) + } + <SimplePostList + {posts} + dateOptions={{ + weekday: "long", + year: "numeric", + month: "long", + day: "numeric", + hour: "2-digit", + minute: "2-digit", + timeZoneName: "long", + }} + /> + { + (next || previous) && ( + <nav> + { + previous && ( + <p> + < <a href={`/blog/${Astro.props.previous}`}>Anterior</a> + </p> + ) + } + <span class="small">{format}</span> + { + next && ( + <p><a href={`/blog/${Astro.props.next}`}>Próximo</a> ></p> + ) + } + </nav> + ) + } + <DateSelector {date} {years} {months} {days} /> + </section> </main> </Base> + +<style> + nav { + display: flex; + align-items: center; + padding-block: calc(var(--size-2) * 1em); + gap: calc(var(--size-2) * 1em); + justify-content: center; + & > p { + border-radius: calc(var(--size-0) * 1em); + border-width: 1px; + box-shadow: 0 1px 2px var(--color-light); + font-size: calc(var(--size-3) * 1rem); + font-weight: 500; + padding-inline: calc(var(--size-3) * 1em); + padding-block: calc(var(--size-2) * 1em); + display: inline-flex; + gap: calc(var(--size-2) * 1em); + align-items: center; + justify-content: center; + height: 2ch; + } + } +</style> |